## Step 1: Define the symbolic variables
Let's define the symbolic variables for the problem:
- $x_1$ represents the acres of apple trees
- $x_2$ represents the acres of peach trees

## Step 2: Formulate the objective function
The profit per acre of apples is $15 and the profit per acre of peaches is $25. The objective function to maximize profit is:
\[ \text{Maximize:} \quad 15x_1 + 25x_2 \]

## 3: Define the constraints
1. Amanda has 4000 acres of land: $x_1 + x_2 \leq 4000$
2. Apple trees cost $50 for their saplings, and peach trees cost $80 for their saplings, with a budget of $30000: $50x_1 + 80x_2 \leq 30000$
3. Apple trees take 3 hours to maintain per acre, and peach trees take 5 hours to maintain per acre, with 600 available hours: $3x_1 + 5x_2 \leq 600$
4. Non-negativity constraints: $x_1 \geq 0, x_2 \geq 0$

## 4: Symbolic representation of the problem
```json
{
    'sym_variables': [('x1', 'acres of apple trees'), ('x2', 'acres of peach trees')],
    'objective_function': '15*x1 + 25*x2',
    'constraints': [
        'x1 + x2 <= 4000',
        '50*x1 + 80*x2 <= 30000',
        '3*x1 + 5*x2 <= 600',
        'x1 >= 0',
        'x2 >= 0'
    ]
}
```

## 5: Gurobi code to solve the problem
```python
import gurobipy as gp

# Create a new model
m = gp.Model("Amanda_Trees")

# Define the variables
x1 = m.addVar(name="apple_trees", lb=0)
x2 = m.addVar(name="peach_trees", lb=0)

# Objective function
m.setObjective(15*x1 + 25*x2, gp.GRB.MAXIMIZE)

# Add constraints
m.addConstr(x1 + x2 <= 4000, name="land_constraint")
m.addConstr(50*x1 + 80*x2 <= 30000, name="budget_constraint")
m.addConstr(3*x1 + 5*x2 <= 600, name="maintenance_constraint")

# Solve the model
m.optimize()

# Print the solution
if m.status == gp.GRB.OPTIMAL:
    print("Optimal solution found.")
    print(f"Acres of apple trees: {x1.varValue}")
    print(f"Acres of peach trees: {x2.varValue}")
    print(f"Max Profit: {m.objVal}")
else:
    print("No optimal solution found.")
```