Help with understanding the Memory Map of MLX90393
This datasheet can be a bit confusing, but I have figured this out.
Here is the format of the Write Register command:

The actual command is 0x60 (bits abc zero as recommended in the datasheet)
From page 18:

The argument for the volatile memory access commands (RR/WR) «abc»
should be set to 0x0h, in order to get normal read-out and write of
the memory.

Looking at the code for the first write, we have:

config = [0x00, 0x5C, 0x07]
bus.write_i2c_block_data(0x0C, 0x60, config)

The bus_write_i2c_block() specifies the device address (0x12), the command (0x60) and the config block.
The config structure is ordered as Register Address, Data Low, Data High (Look back at the format and you will see that the last command item is the register address; as it is first in this list it is reasonable to see it as in reverse reading order)
The data to be loaded where I have expanded only the least significant byte:

So the gain field has been set to 0x05
So to use the block write function, look at the register you need, set up the bitfields from the memory map as required and separate to high and low byte then use the config this way:

config = [register address, low byte, high byte]

The bitfields are described in section 15.1
The command

bus.write_byte(0x0C, 0x3E)

is command 0x3[zyxt] with the zyxt (Z axis, Y axis, X axis, Temperature) bits set to 1110; measurements will be done on the Z,Y and X axis and the temperature measurements will not be done as the bits enable the first 3 items and not the last.
Note that the address shift left operation (as required by the address field) appears to be implemented in the write function.
The call

config = [0x02, 0xB4, 0x08]
bus.write_i2c_block_data(0x0C, 0x60, config)

Which sets the RES fields has 2 as the register argument, and the actual register with those fields in indeed register address 2.
With devices like this, you need to map the bitfields for each piece of functonality in a given 16 bit word (by using a template and seeing what the final result is).
In this example, the author has used hard coded constants.
You could use something like this (C syntax) for a more generic approach:
typedef struct
{
uint8_t Address;
uint8_t DataLow;
uint8_t Datahigh;
}configdata;

// then a declaration
    configdata config;
    
//    and then fill it with:
    
    config.Address = &lt;address&gt;;
    config.DataLow = &lt;data low&gt;;
    config.Datahigh = &lt;data high&gt;;

That should get you going.