Is there any way to pro-grammatically create product categories and assign thumbnails in PHP and WooCommerce?

wp_insert_term() works fine for this sort of thing.

You haven’t given any context, but here’s a quick example I made that, on every page load, adds a random WooCommerce product category(not duplicates though), and an associated random image, from a list of image id’s in MY media library(change $existing_image_ids to your own ids for this to work).

// page load creates a random product category, and an associated image
add_action( 'init', 'rand_product_cat_w_rand_image' );
function rand_product_cat_w_rand_image() {

    $test_product_cats = [
        'Test Category 1',
        'Test Category 2',
        'Test Category 3',
        'Test Category 4',
        'Test Category 5'
    ];

    $existing_image_ids = [
        '144',
        '143',
        '142',
        '141',
        '140'
    ];

    $rand_cat = rand( 0, 4 );
    $rand_img = rand( 0, 4 );

    $new_cat_title = $test_product_cats[$rand_cat]; // title of product category
    $new_img_id = $existing_image_ids[$rand_img]; // id of image you want to use from your media library

    $new_cat_added = wp_insert_term( $new_cat_title, 'product_cat' ); // 'product_cat' is woocommerce product category taxonomy, and were adding a new category with title

    if(is_wp_error( $new_cat_added )) {
        return; // there was an error adding new product category, usually because it already exists with only 5 available test categories
    }
    else {
        add_term_meta( $new_cat_added['term_id'], 'thumbnail_id', $new_img_id, true ); // add image to new product category, etc.
    }    
}

// This bit is just copied from WooCommerce docs for showing product category image:
// REF: https://docs.woocommerce.com/document/woocommerce-display-category-image-on-category-archive/
add_action( 'woocommerce_archive_description', 'woocommerce_category_image', 2 );
function woocommerce_category_image() {
    if ( is_product_category() ){
        global $wp_query;
        $cat = $wp_query->get_queried_object();
        $thumbnail_id = get_woocommerce_term_meta( $cat->term_id, 'thumbnail_id', true );
        $image = wp_get_attachment_url( $thumbnail_id );
        if ( $image ) {
            echo '<img src="' . $image . '" alt="' . $cat->name . '" />';
        }
    }
}

Tested and works.