To solve this optimization problem, we first need to define the decision variables and the objective function. Let's denote the number of batches of pancakes as \(P\) and the number of batches of bagels as \(B\). The objective is to maximize profit, which is $25 per batch of pancakes and $30 per batch of bagels.

The constraints are based on the time availability for Daniel and David:
- Each batch of pancakes requires 25 minutes of Daniel's time.
- Each batch of bagels requires 9 minutes of Daniel's time.
- Daniel has 150 minutes available.
- Each batch of pancakes requires 15 minutes of David's time.
- Each batch of bagels requires 20 minutes of David's time.
- David has 350 minutes available.

The mathematical formulation can be written as follows:
- Objective function: Maximize \(25P + 30B\)
- Constraints:
  - \(25P + 9B \leq 150\) (Daniel's time constraint)
  - \(15P + 20B \leq 350\) (David's time constraint)
  - \(P \geq 0, B \geq 0\) (Non-negativity constraints since the number of batches cannot be negative)

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

```python
from gurobipy import *

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

# Define the decision variables
P = m.addVar(vtype=GRB.INTEGER, name="pancakes")
B = m.addVar(vtype=GRB.INTEGER, name="bagels")

# Set the objective function: Maximize profit
m.setObjective(25*P + 30*B, GRB.MAXIMIZE)

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

# Optimize the model
m.optimize()

# Print the results
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Number of batches of pancakes: {P.x}")
    print(f"Number of batches of bagels: {B.x}")
    print(f"Maximum profit: ${25*P.x + 30*B.x:.2f}")
else:
    print("No optimal solution found")
```