Apparently some matrices are small, so there is no need to allocate the maximum size 1000x1000. One way is to put the matrix in a structure to make it easier to keep track of size:
struct s_matrix
{
    int **matrix;
    int N; //one side of the square matrix N x N
};
typedef struct s_matrix Matrix;
Then allocate and free the matrix
void allocate_matrix(Matrix *m, int N)
{
    m->N = N;
    m->matrix = (int**)malloc(N * sizeof(int*));
    *m->matrix = (int*)malloc(N * N * sizeof(int));
    for (int i = 0; i < N; i++) 
        m->matrix[i] = *m->matrix + i * N;
    for (int i = 0; i < N; i++) 
        for (int j = 0; j < N; j++) 
            m->matrix[i][j] = 0; 
}
void free_matrix(Matrix *m)
{
    if (!m) return;
    if (!m->matrix) return;
    free(*m->matrix);
    free(m->matrix);
}
Now we can declare how many matrices we need. It looks like this number is fixed at 30, so I don't think we need dynamic allocation.
int main()
{
    const int max_count = 30;        
    Matrix list[max_count]; 
    for (int i = 0; i < max_count; i++) 
        list[i].matrix = NULL; 
    allocate_matrix(&list[0], 3);//allocate 3x3 matrix
    allocate_matrix(&list[1], 1000);//1000x1000
    allocate_matrix(&list[2], 4000);//4000x4000
    int **m;
    m = list[0].matrix;
    m[0][0] = 0; 
    m[0][1] = 1; 
    m[0][2] = 2; 
    for (int i = 0; i < 3; i++) 
        for (int j = 0; j < 3; j++) 
            printf("%02d %s", m[i][j], (j == 2) ? "\n" : ""); 
    //...
    for (int i = 0; i < max_count; i++) 
        free_matrix(&list[i]); 
    printf("hey it worked, or maybe it didn't, or it did but there is memory leak\n");
    return 0;
}