1. Yes get_paired_patch_3D function provides same location patches from the MR and CT images.
2. I am not sure about the single sample thing. are you refering to the batch size?
3. I tried things like this:
# print(np.shape(patches_MR))  #(18, 500, 32, 32, 32)
# print(np.shape(patches_CT))  #(18, 500, 32, 32, 32)

class Dataset(data.Dataset):
    'characterizes a dataset for pytorch'
    def __init__(self, patches_MR, patches_CT):
        self.patches_MR = patches_MR
        self.patches_CT = patches_CT
        # self.patches_MR = patches_MR
        # self.patches_CT = patches_CT

    def __len__(self):
        'denotes the total number of samples'
        return len(self.patches_MR)

    def __getitem__(self, index):
        'Generates one sample of data'
        #select sample
        x = self.patches_MR[index]
        y = self.patches_CT[index]
        # Unsqueeze channel dimension
        x = x.unsqueeze(0)
        y = y.unsqueeze(0)
        return x, y

and then in the train.py:
train_dataset = Dataset(patches_MR,patches_CT)
train_loader = data.DataLoader(train_dataset,batch_size=5,shuffle=True)
print('train directory has {} samples'.format(len(train_dataset)))
# np.shape(train_dataset)
# Out[242]: (18, 2, 500, 32, 32, 32)

As you can see the train_dataset has 2 channels: if I am not wrong one for MR and one for CT and did you use unsqueeze for that reason?
4.  Yes while extracting patches I did not use any shuffle which I intend to use in the torch.utils.data.DataLoader as you can see in the codes.
5. I want to feed the input(MR) and ground truth(CT) in the UNet/GAN as:
        for i, sample in enumerate(train_loader):
            netG.train()
            netD.train()
            time_batch_load = time.time() - time_batch_start
            time_compute_start = time.time()
            mr = sample[0].float().to(device) 
            ct = sample[1].float().to(device)
            batch_size_temp = len(sample[0])
            outputG = netG(mr)