Thanks for the information.
I would try to avoid the preprocessing with bounding boxes, as this would give you more flexibility but would also add more complexity to the code, which is apparently not needed for your use case.
Since the digits are located in the same zones, you could write a slice_image method, which could use passed size to return a batch of digits from a single image.
While there are many ways to write this code, here is a small example using unfold:
# create input tensor
x = torch.stack([torch.ones(32, 32) * idx for idx  in range(16)])
x = x.view(4, 4, 32, 32).permute(0, 2, 1, 3).contiguous().view(4*32, 4*32)
plt.imshow(x.numpy())


def slice_image(image, size):
    batch = image.unfold(0, size, size).unfold(1, size, size) # [4, 4, 32, 32]
    # flatten to [16, 32, 32]
    batch = batch.contiguous().view(-1, size, size)
    # add channel dim
    batch = batch.unsqueeze(1)
    return batch

Note that you would create a batch of 16 samples in this way, so the batch_size in the DataLoader would be a multiplicative factor and you would need to flatten the batch dimensions in your training loop:
for data in loader:
    # data.shape is [batch_size, 16, 1, 32, 32]
    data = data.view(-1, 1, 32, 32)
    # data.shape is [batch_size*16, 1, 32, 32]