Both approaches should yield the same result, if you are using the same setup besides the out_channels.
Note that predXYCoord uses kernel_size=2, while the others use a kernel size of 1.
Here is a small example:
# Single layer
input = torch.randn(1, 10, 32, 32, requires_grad=True)
conv1 = nn.Conv2d(10, 3, 3, 1, 1, bias=False)

out1 = conv1(input)

out1[:, :2].mean().backward(retain_graph=True)
out1[:, 2:].mean().backward()

input_grad_reference = input.grad.clone()
conv_grad_reference = conv1.weight.grad.clone()

input.grad.zero_()

# Two layers
conv2 = nn.Conv2d(10, 2, 3, 1, 1, bias=False)
conv3 = nn.Conv2d(10, 1, 3, 1, 1, bias=False)
with torch.no_grad():
    conv2.weight.copy_(conv1.weight[:2])
    conv3.weight.copy_(conv1.weight[2:])
    
out2 = conv2(input)
out3 = conv3(input)

out2.mean().backward()
out3.mean().backward()

# Compare
print((input.grad == input_grad_reference).all())
> tensor(True)
print((conv2.weight.grad == conv_grad_reference[:2]).all())
> tensor(True)
print((conv3.weight.grad == conv_grad_reference[2:]).all())
> tensor(True)