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

Let's denote:
- $M$ as the number of muffins to be made.
- $C$ as the number of milk cakes to be made.

The objective is to maximize profit. Given that each muffin sells for a profit of $6.5 and each milk cake sells for a profit of $8.5, the total profit $P$ can be represented by the equation:
\[ P = 6.5M + 8.5C \]

We have two main constraints based on the problem description:
1. **Milk Availability Constraint**: The total amount of milk used for muffins and milk cakes cannot exceed 25,000 grams. Since each muffin requires 15 grams of milk and each milk cake requires 100 grams of milk, this constraint can be written as:
\[ 15M + 100C \leq 25000 \]
2. **Minimum Muffins and Milk Cakes Ratio Constraint**: The number of milk cakes must be at least twice the number of muffins, and there must be at least 50 muffins made. This gives us two constraints:
\[ C \geq 2M \]
\[ M \geq 50 \]

Additionally, since we cannot produce a negative number of muffins or milk cakes, we have:
\[ M \geq 0 \]
\[ C \geq 0 \]

Now, let's translate these constraints and the objective function into Gurobi code in Python:

```python
from gurobipy import *

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

# Define variables
M = m.addVar(lb=0, vtype=GRB.INTEGER, name="Muffins")
C = m.addVar(lb=0, vtype=GRB.INTEGER, name="Milk_Cakes")

# Objective function: Maximize profit
m.setObjective(6.5*M + 8.5*C, GRB.MAXIMIZE)

# Constraints
m.addConstr(15*M + 100*C <= 25000, "Milk_Availability")
m.addConstr(C >= 2*M, "Milk_Cakes_vs_Muffins")
m.addConstr(M >= 50, "Minimum_Muffins")

# Optimize model
m.optimize()

# Print results
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Muffins: {M.x}")
    print(f"Milk Cakes: {C.x}")
    print(f"Maximum Profit: ${6.5*M.x + 8.5*C.x:.2f}")
else:
    print("No optimal solution found")
```