To solve this optimization problem, we first need to identify the decision variables, constraints, and the objective function.

- **Decision Variables:**
  - Let \(x_c\) be the number of tons of chocolate syrup produced per week.
  - Let \(x_{cm}\) be the number of tons of caramel syrup produced per week.

- **Constraints:**
  - The factory can make at most 15 tons of each syrup per week:
    - \(x_c \leq 15\)
    - \(x_{cm} \leq 15\)
  - The minimum production requirements:
    - \(x_c \geq 2\)
    - \(x_{cm} \geq 3\)
  - The heating machine constraint: Each ton of syrup requires 3 hours, and the machine is available for at most 50 hours per week.
    - \(3x_c + 3x_{cm} \leq 50\)

- **Objective Function:**
  - Maximize profit: \(500x_c + 350x_{cm}\)

Given these elements, we can formulate the linear programming problem as follows:

Maximize \(500x_c + 350x_{cm}\) subject to:
1. \(x_c \leq 15\)
2. \(x_{cm} \leq 15\)
3. \(x_c \geq 2\)
4. \(x_{cm} \geq 3\)
5. \(3x_c + 3x_{cm} \leq 50\)
6. \(x_c, x_{cm} \geq 0\) (non-negativity constraint, implicitly satisfied by constraints 3 and 4)

Now, let's translate this into Gurobi code in Python:

```python
from gurobipy import *

# Create a new model
model = Model("Syrup_Factory")

# Decision variables
x_c = model.addVar(lb=2, ub=15, vtype=GRB.CONTINUOUS, name="Chocolate_Syrup")
x_cm = model.addVar(lb=3, ub=15, vtype=GRB.CONTINUOUS, name="Caramel_Syrup")

# Objective function
model.setObjective(500*x_c + 350*x_cm, GRB.MAXIMIZE)

# Constraints
model.addConstr(x_c <= 15, "Max_Chocolate")
model.addConstr(x_cm <= 15, "Max_Caramel")
model.addConstr(3*x_c + 3*x_cm <= 50, "Heating_Machine")

# Optimize model
model.optimize()

# Print results
if model.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Chocolate Syrup: {x_c.x} tons")
    print(f"Caramel Syrup: {x_cm.x} tons")
    print(f"Maximum Profit: ${model.objVal}")
else:
    print("No optimal solution found.")
```