To solve the optimization problem described, we first need to convert the natural language description into a symbolic representation. This involves defining variables for the quantities of interest (batches of pancakes and bagels), formulating the objective function that represents the total profit, and specifying the constraints based on the time availability of Daniel and David.

Let's denote:
- $x_1$ as the number of batches of pancakes to be made.
- $x_2$ as the number of batches of bagels to be made.

The objective function, which is to maximize the total profit, can be represented as:
\[ \text{Maximize} \quad 25x_1 + 30x_2 \]

The constraints are based on the time availability:
- Daniel has 150 minutes available: $25x_1 + 9x_2 \leq 150$
- David has 350 minutes available: $15x_1 + 20x_2 \leq 350$

Additionally, we know that $x_1 \geq 0$ and $x_2 \geq 0$, as the number of batches cannot be negative.

The symbolic representation in JSON format is:
```json
{
    'sym_variables': [('x1', 'batches of pancakes'), ('x2', 'batches of bagels')],
    'objective_function': '25*x1 + 30*x2',
    'constraints': ['25*x1 + 9*x2 <= 150', '15*x1 + 20*x2 <= 350', 'x1 >= 0', 'x2 >= 0']
}
```

Now, let's implement this problem using Gurobi in Python:
```python
from gurobipy import *

# Create a new model
m = Model("Bakery_Optimization")

# Define the variables
x1 = m.addVar(vtype=GRB.CONTINUOUS, name="batches_of_pancakes", lb=0)
x2 = m.addVar(vtype=GRB.CONTINUOUS, name="batches_of_bagels", lb=0)

# Set the objective function
m.setObjective(25*x1 + 30*x2, GRB.MAXIMIZE)

# Add constraints
m.addConstr(25*x1 + 9*x2 <= 150, "Daniel's_time")
m.addConstr(15*x1 + 20*x2 <= 350, "David's_time")

# Optimize the model
m.optimize()

# Print the results
if m.status == GRB.OPTIMAL:
    print(f"Optimal solution: {x1.varName} = {x1.x}, {x2.varName} = {x2.x}")
    print(f"Maximum profit: {m.objVal}")
else:
    print("No optimal solution found")
```