To solve the given optimization problem, we first need to define the symbolic representation of the variables and the objective function, as well as list out all constraints based on the natural language description provided.

Let's denote:
- $x_1$ as the amount (in kilograms) of silage fed to each cow per day.
- $x_2$ as the amount (in kilograms) of mixed grains fed to each cow per day.

The objective function aims to minimize the total cost of feeding the cows. Given that silage costs $215 per kilogram and mixed grains cost $320 per kilogram, the objective function can be represented as:
\[ \text{Minimize} \quad 50(215x_1 + 320x_2) \]
Here, we multiply by 50 because there are 50 cows.

The constraints based on the nutritional requirements and limits for each cow are as follows:
1. Protein requirement: $0.5x_1 + 0.2x_2 \geq 2$
2. Minerals requirement: $0.1x_1 + 0.2x_2 \geq 1.5$
3. Vitamins limit: $0.2x_1 + 0.1x_2 \leq 1$

Thus, the symbolic representation of the problem in JSON format is:
```json
{
  'sym_variables': [('x1', 'amount of silage per cow per day'), ('x2', 'amount of mixed grains per cow per day')],
  'objective_function': '50*(215*x1 + 320*x2)',
  'constraints': [
    '0.5*x1 + 0.2*x2 >= 2',
    '0.1*x1 + 0.2*x2 >= 1.5',
    '0.2*x1 + 0.1*x2 <= 1'
  ]
}
```

To solve this optimization problem using Gurobi in Python, we can use the following code:
```python
from gurobipy import *

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

# Define variables
x1 = m.addVar(name="silage", lb=0)
x2 = m.addVar(name="mixed_grains", lb=0)

# Set objective function
m.setObjective(50*(215*x1 + 320*x2), GRB.MINIMIZE)

# Add constraints
m.addConstr(0.5*x1 + 0.2*x2 >= 2, name="protein_requirement")
m.addConstr(0.1*x1 + 0.2*x2 >= 1.5, name="minerals_requirement")
m.addConstr(0.2*x1 + 0.1*x2 <= 1, name="vitamins_limit")

# Optimize model
m.optimize()

# Print results
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Silage per cow per day: {x1.x}")
    print(f"Mixed grains per cow per day: {x2.x}")
    print(f"Total cost: {m.objVal}")
else:
    print("No optimal solution found")
```
This code defines the variables, sets up the objective function to minimize the total cost, adds the constraints based on the nutritional requirements and limits, optimizes the model, and then prints out the results if an optimal solution is found.