Starting on writing J5 components with xbMusic I discover a much better way of creating tags progrmatically (see previous version here). Most of this could probably be done in J3 but I didn't realise that. Essentially instead of creating a Table object and separately calling the bind() check() and store() functions you can create a Tags model and just call save. I think the reason I didn't do this before was because of wanting to check within the createGetTag() function that the tag and its parent didn't already exist.

The code below is written with static functions to include in a Helper class - obviously you can remove the static keywords and replace self:: with $this-> for use in other classes. The function now returns an object containing the id and title for the new tag.

use Joomla\CMS\Factory;

	 * @name createTag()
	 * @desc creates a tag with the passed title and optional other fields including parent_id and returns an object containg the id and title
	 *     doesn't check if tag already exists - do this first with checkValueExists() or you'll get an error message.
	 * @param array $tagdata - ['title'=>$mynewtitle
	 * @param boolean $silent - supress messages if true. You'll still get a message if the tag already exists.
	 * @return \stdClass - (id->int, title->string). WIll be empty if the function failed
	public static function createTag(array $tagdata, $silent = false) {
	    $app = Factory::getApplication();
	    $errmsg = '';
	    $infomsg = '';
        $wynik = new \stdClass();
        //set defaults for status & parent
        if (!key_exists('published', $tagdata))  $tagdata['published'] = 1;
        if (!key_exists('parent_id', $tagdata))  $tagdata['parent_id'] = 1;
        if (!key_exists('langauge', $tagdata))  $tagdata['language'] = '*';
        if (!key_exists('description', $tagdata))  $tagdata['description'] = '';       
        // Create new tag.
        $tagModel = Factory::getApplication()->bootComponent('com_tags')
           ->getMVCFactory()->createModel('Tag', 'Administrator', ['ignore_request' => true]);	        
        if (!$tagModel->save($tagdata)) {
            $errmsg = $tagModel->getError();	            
        } else {
	        $tagid = $tagModel->getState('');
	        $infomsg .= 'New tag '.$tagdata['title'].' created with id '.$tagid;
	        $wynik->id = $tagid;
            $wynik->title = $tagdata['title'];	            
	    if ($errmsg != '') $app->enqueueMessage($errmsg, 'Warning');
        if ($infomsg != '') $app->enqueueMessage($infomsg);
        return $wynik;

 and here is a separate function to check if the tag already exists before you call createTag()  

use Joomla\CMS\Factory;
use Joomla\Database\DatabaseInterface;

	 * @name checkValueExists()
	 * @desc returns its id if given value exists in given table column (case insensitive)
	 * @param string $value - text to check
	 * @param string $table - the table to check in
	 * @param string $col- the column to check
	 * @param string $where - optional additional where condition (AND). should be quoted
	 * @return int|boolean - id if value is found in column, otherwise false
	public static function checkValueExists( $value,  $table, $col, $where = '') {
	    //$db = Factory::getDbo();
	    $db = Factory::getContainer()->get(DatabaseInterface::class);
	    $query = $db->getQuery(true);
	    if ($where != '') $query->where($where);
	    $res = $db->loadResult();
	    if ($res > 0) {
	        return $res;
	    return false;

Just for completeness here's a function to create several tags at once, again you'll need to check each doesn't already exist while building the array to create

	 * @name createTags()
	 * @desc function to create a tag with title, parent_tag_id, status, and optional description
	 * @param assoc array $tagdata
	 * @param boolean $silent - enable messages if false. You'll still get a message if the tag already exists.
	 * @return array of objects containg id and title of new tags
	public static function createTags(array $tagsarr, $silent = true) {
	    $result = array();
	    foreach ($tagsarr as $tag) {	        
	        $wynik = self::createTag($tag, $silent);
	        if (!empty($wynik)) $result[] = $wynik;
	    return $result;