Here's the Gurobi code for the optimization problem:

```python
import gurobipy as gp

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

# Create variables
peggy_hours = m.addVar(lb=0, name="peggy_hours")
hank_hours = m.addVar(lb=0, name="hank_hours")
george_hours = m.addVar(lb=0, name="george_hours")

# Set objective function
m.setObjective(8 * peggy_hours * hank_hours + george_hours**2 + peggy_hours, gp.GRB.MINIMIZE)

# Add constraints
m.addConstr(8 * hank_hours**2 + 6 * george_hours**2 >= 28, "paperwork_competence_1")
m.addConstr(peggy_hours + 8 * hank_hours + 6 * george_hours >= 28, "paperwork_competence_2")
m.addConstr(2 * hank_hours + 3 * george_hours >= 23, "work_quality_1")
m.addConstr(peggy_hours**2 + 3 * george_hours**2 >= 24, "work_quality_2")
m.addConstr(peggy_hours**2 + 2 * hank_hours**2 + 3 * george_hours**2 >= 21, "work_quality_3")
m.addConstr(peggy_hours + 2 * hank_hours + 3 * george_hours >= 21, "work_quality_4")
m.addConstr(9 * peggy_hours**2 - 7 * hank_hours**2 >= 0, "constraint_7")
m.addConstr(peggy_hours + 3 * george_hours <= 79, "work_quality_5")
m.addConstr(2 * hank_hours**2 + 3 * george_hours**2 <= 58, "work_quality_6")


# Optimize model
m.optimize()

# Print results
if m.status == gp.GRB.OPTIMAL:
    print('Optimal objective: %g' % m.objVal)
    print('Peggy hours: %g' % peggy_hours.x)
    print('Hank hours: %g' % hank_hours.x)
    print('George hours: %g' % george_hours.x)
elif m.status == gp.GRB.INF_OR_UNBD:
    print('Model is infeasible or unbounded')
    exit(0)
elif m.status == gp.GRB.INFEASIBLE:
    print('Model is infeasible')
    exit(0)
elif m.status == gp.GRB.UNBOUNDED:
    print('Model is unbounded')
    exit(0)
else:
    print('Optimization ended with status %d' % m.status)
    exit(0)

```