To solve this optimization problem, we first need to define the symbolic representation of the variables and the objective function, along with the constraints based on the natural language description provided.

Let's denote:
- \(x_1\) as the number of small teams.
- \(x_2\) as the number of large teams.

The objective is to minimize the total cost. Given that a small team costs $5000 and a large team costs $15000, the objective function can be represented algebraically as:
\[ \text{Minimize:} \quad 5000x_1 + 15000x_2 \]

The constraints are based on two main requirements:
1. The total tasks per hour should be at least 100.
2. The maximum number of supervisors should not exceed 10.

Given that a small team can perform 8 tasks per hour and requires 1 supervisor, and a large team can perform 20 tasks per hour and requires 3 supervisors, the constraints can be represented as:
\[ \text{Constraints:} \]
- For tasks: \(8x_1 + 20x_2 \geq 100\)
- For supervisors: \(x_1 + 3x_2 \leq 10\)

Additionally, since we cannot form a negative number of teams, we have non-negativity constraints:
- \(x_1 \geq 0\)
- \(x_2 \geq 0\)

And since the number of teams must be an integer (you can't form half a team), both \(x_1\) and \(x_2\) are integers.

In symbolic representation, we have:
```json
{
    'sym_variables': [('x1', 'number of small teams'), ('x2', 'number of large teams')],
    'objective_function': '5000*x1 + 15000*x2',
    'constraints': ['8*x1 + 20*x2 >= 100', 'x1 + 3*x2 <= 10', 'x1 >= 0', 'x2 >= 0']
}
```

Now, let's implement this problem in Gurobi using Python:

```python
from gurobipy import *

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

# Define the variables
x1 = m.addVar(vtype=GRB.INTEGER, name="small_teams")
x2 = m.addVar(vtype=GRB.INTEGER, name="large_teams")

# Set the objective function
m.setObjective(5000*x1 + 15000*x2, GRB.MINIMIZE)

# Add constraints
m.addConstr(8*x1 + 20*x2 >= 100, "tasks")
m.addConstr(x1 + 3*x2 <= 10, "supervisors")
m.addConstr(x1 >= 0, "non_neg_small_teams")
m.addConstr(x2 >= 0, "non_neg_large_teams")

# Optimize the model
m.optimize()

# Print the results
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Number of small teams: {x1.x}")
    print(f"Number of large teams: {x2.x}")
    print(f"Total cost: ${5000*x1.x + 15000*x2.x}")
else:
    print("No optimal solution found")
```