because model1, model2, model3 and model are referring to the same object. You have to use copy.deepcopy() to create an independent copy of the model. your second, question would be solved with copy.deepcopy()
yes, you can compute
loss1 = criterion(outputs1, labels)
loss2 = criterion(outputs2, labels)
loss3 = criterion(outputs3, labels)
loss = loss1 + loss2 + loss3
loss.backward()

regarding optimizer.step(), you first have to add all your models parameters to the optimizer before calling the step.
torch.optim.SGD(list(model1.parameters()) + list(model2.parameters() + list(model3.parameters())