You can just combine them in the training loop:
for data, target in train_loader:
    output = model1(data)
    output = model2(output)
    output = model3(output)

   # or use a loop instead

or just wrap them in another nn.Module and treat them as layers:
class MyHugeModel(nn.Module):
    def __init__(self, models):
        super(MyHugeModel, self).__init__()
        self.models = models
        
    def forward(self, x):
        for model in self.models[:-1]:
            x = F.relu(model(x))
        x = self.models[-1](x)  # don't use relu for last model
        return x
            
class MySmallModel(nn.Module):
    def __init__(self):
        super(MySmallModel, self).__init__()
        self.lin = nn.Linear(10, 10)
        
    def forward(self, x):
        x = self.lin(x)
        return x


models = nn.ModuleList()
for _ in range(10):
    models.append(MySmallModel())

model = MyHugeModel(models)
x = torch.randn(1, 10)
output = model(x)

Using this approach, you can pass all parameters as model.parameters() to your optimizer.