First code
The graph cannot be visualized because the layers are not in nn container.
You should put them into a container like below,
self.nn_shared_layers = nn.ModuleList(*self.shared_layers)
self.nn_actor_subnet = nn.ModuleList(*self.actor_subnet)
self.nn_critic_subnet = nn.ModuleList(*self.critic_subnet)

I recommend you to use nn.Sequential instead of nn.ModuleList.
Except the shared_layers, your forward function is designed in a serial manner. In short,
You can rewrite your forward function like
# In __init__
self.nn_actor_subnet = nn.Sequential(*self.actor_subnet)
# In forward
action_logits = self.nn_actor_subnet(x)

Second Code
I guess your code is well modified to visualize the graph but the reason that your result seems weird comes from not using activation functions.
I don’t know how small your learning rate and which optimizer you use. But if the learning rate is not that big such as 1, the problem is usually mis-designed network.

class Conv3DModelFree(nn.Module):
    def __init__(self, in_shape, num_actions, **kwargs):
        fc_layers = kwargs["fc_layers"]
        super(Conv3DModelFree, self).__init__(
            num_actions, features_out=fc_layers[-1])
        # super().__init__()
        conv_layers = kwargs["conv_layers"]

        self.shared_layers = []
        self.num_actions = num_actions
        self.in_shape = in_shape
        self.num_channels = in_shape[0]
        self.num_frames = kwargs["num_frames"]
        next_inp = None
        # =============================================================================
        # FEATURE EXTRACTOR SUBMODULE
        # =============================================================================
        for i, cnn in enumerate(conv_layers):
            if i == 0:
                self.shared_layers.append(nn.Conv3d(
                    self.num_channels, cnn[0], kernel_size=cnn[1], stride=cnn[2]))
                self.shared_layers.append(nn.LeakyReLU())
            else:
                self.shared_layers.append(nn.Conv3d(
                    next_inp, cnn[0], kernel_size=cnn[1], stride=cnn[2]))
                self.shared_layers.append(nn.LeakyReLU())

            if i == len(conv_layers) - 3:
                self.shared_layers.append(nn.Flatten(start_dim=1))

            next_inp = cnn[0]

        for i, layer in enumerate(self.shared_layers):
            if i == 0:
                fake_inp = torch.zeros(
                    [1, self.num_channels, self.num_frames, *self.in_shape[1:]])
                fake_inp = self.shared_layers[i](fake_inp)
            else:
                fake_inp = self.shared_layers[i](fake_inp)
        next_inp = fake_inp.view(1, -1).size(1)

        # =============================================================================
        # ACTOR AND CRITIC SUBMOODULES
        # =============================================================================
        self.actor_subnet = []
        self.critic_subnet = []
        for i, fc in enumerate(fc_layers):
            if i == 0:
                self.shared_layers.append(nn.Linear(next_inp, fc))
                self.shared_layers.append(nn.LeakyReLU())
            else:
                # Separate submodules for the actor and the critic
                self.actor_subnet.append(nn.Linear(next_inp, fc))
                self.critic_subnet.append(nn.Linear(next_inp, fc))
                self.actor_subnet.append(nn.LeakyReLU())
                self.critic_subnet.append(nn.LeakyReLU())
            next_inp = fc

        self.nn_shared_layers = nn.Sequential(*self.shared_layers)
        self.nn_actor_subnet = nn.Sequential(*self.actor_subnet)
        self.nn_critic_subnet = nn.Sequential(*self.critic_subnet)

    def forward(self, input)
        x = self.nn_shared_layers(input)
        action_logits = self.nn_actor_subnet(x)
        value = self.nn_critic_subnet(x)

        return action_logits, value